/*============================================================================*/
/*  Copyright (C) 2009-2011, iSOFT INFRASTRUCTURE SOFTWARE CO.,LTD.
 *
 *  All rights reserved. This software is iSOFT property. Duplication
 *  or disclosure without iSOFT written authorization is prohibited.
 *
 *  @file       <Can.c>
 *  @brief      <Can driver Module source file>
 *
 * <Compiler: TASKING V3.5    MCU:TC17XX>
 *
 *  @author     <jianan.liu>
 *  @date       <03-18-2014>
 */
/*============================================================================*/

/*=======[R E V I S I O N   H I S T O R Y]====================================*/
/*  <VERSION>    <DATE>    <AUTHOR>    <REVISION LOG>
 *  V1.0.0       20140318  jianan.liu   Initial version
 *                                      these features not support in this version:
 *                                      1. multiple Can Drivers.
 *                                      2. Can transceiver.
 *                                      3. Sleep and weakup
 *  V1.0.1       20140618  bo.zeng      1. change variable name CanCtrlValue to CanNbtr
 *                                      2. add configure item CAN_MCR_REG_VALUE in Can_Cfg.h, for 
 *                                      clock source select
 *                                      3. delete configure item CpuClockRef, because of not used
 *                                      4. add configure item CanNpcr for rx pin select
 *  V1.0.2       20140715  bo.zeng      add lock/unlock  Endinit-protected registers(CLC, FDR)
 *  V1.0.3       20140721  bo.zeng      1. remove CAN_SRC related action.
 *                                      2. adjust interrupt line allocate
 *  V1.0.4       20140827  bo.zeng      1. code sytle
 *                                      2. add configure item CAN_HW_MAX_MAILBOXES
 *                                      3. interrupt line adjust
 *                                      4. use macro CAN_MSPND_CLEAR replace Can_ResetPnd
 *                                      5. use Can_TxPduHandles replace TxPduHandles
 *                                      6. add Can_NodeRegPtrType, Can_MbRegPtrType type
 *                                      7. adjust the way of coping SDU
 */
/*============================================================================*/
/*=======[V E R S I O N  I N F O R M A T I O N]===============================*/
#define CAN_C_AR_MAJOR_VERSION      2
#define CAN_C_AR_MINOR_VERSION      4
#define CAN_C_AR_PATCH_VERSION      0

#define CAN_C_SW_MAJOR_VERSION      1
#define CAN_C_SW_MINOR_VERSION      0
#define CAN_C_SW_PATCH_VERSION      4

/*=======[I N C L U D E S]====================================================*/
#include "Can.h"
#if (STD_ON == CAN_DEV_ERROR_DETECT)
#include "Det.h"
#endif /* STD_ON == CAN_DEV_ERROR_DETECT */
#if (STD_ON == CAN_DEM_ERROR_DETECT)
#include "Dem.h"
#endif /* STD_ON == CAN_DEM_ERROR_DETECT */
#include "CanIf_Cbk.h"
#include "SchM_Can.h"
#include "Can_Regs.h"
#include "Can_Irq.h"

/*=======[V E R S I O N  C H E C K]===========================================*/
#if (CAN_C_AR_MAJOR_VERSION != CAN_H_AR_MAJOR_VERSION)
    #error "Can.c:Mismatch in Specification Major Version"
#endif /* CAN_C_AR_MAJOR_VERSION != CAN_H_AR_MAJOR_VERSION */
#if (CAN_C_AR_MINOR_VERSION != CAN_H_AR_MINOR_VERSION)
    #error "Can.c:Mismatch in Specification Minor Version"
#endif /* CAN_C_AR_MINOR_VERSION != CAN_H_AR_MINOR_VERSION */
#if (CAN_C_AR_PATCH_VERSION != CAN_H_AR_PATCH_VERSION)
    #error "Can.c:Mismatch in Specification Patch Version"
#endif /* CAN_C_AR_PATCH_VERSION != CAN_H_AR_PATCH_VERSION */
#if (CAN_C_SW_MAJOR_VERSION != CAN_H_SW_MAJOR_VERSION)
    #error "Can.c:Mismatch in Specification Major Version"
#endif /* CAN_C_SW_MAJOR_VERSION != CAN_H_SW_MAJOR_VERSION */
#if (CAN_C_SW_MINOR_VERSION != CAN_H_SW_MINOR_VERSION)
    #error "Can.c:Mismatch in Specification Minor Version"
#endif /* CAN_C_SW_MINOR_VERSION != CAN_H_SW_MINOR_VERSION */


#if (STD_ON == CAN_DEV_ERROR_DETECT)
#if (2 != DET_H_AR_MAJOR_VERSION)
    #error "Can.c:Mismatch in Specification Major Version"
#endif
#if (2 != DET_H_AR_MINOR_VERSION)
    #error "Can.c:Mismatch in Specification Minor Version"
#endif
#endif /* STD_ON == CAN_DEV_ERROR_DETECT */

#if (STD_ON == CAN_DEM_ERROR_DETECT)
#if (3 != DEM_H_AR_MAJOR_VERSION)
    #error "Can.c:Mismatch in Specification Major Version"
#endif
#if (1 != DEM_H_AR_MINOR_VERSION)
    #error "Can.c:Mismatch in Specification Minor Version"
#endif
#endif /* STD_ON == CAN_DEM_ERROR_DETECT */

#if (3 != CANIF_CBK_H_AR_MAJOR_VERSION)
    #error "Can.c:Mismatch in Specification Major Version"
#endif
#if (2 != CANIF_CBK_H_AR_MINOR_VERSION)
    #error "Can.c:Mismatch in Specification Minor Version"
#endif

#if (1 != SCHM_CAN_H_AR_MAJOR_VERSION)
    #error "Can.c:Mismatch in Specification Major Version"
#endif
#if (1 != SCHM_CAN_H_AR_MINOR_VERSION)
    #error "Can.c:Mismatch in Specification Minor Version"
#endif

#if (2 != CAN_REG_H_AR_MAJOR_VERSION)
    #error "Can.c:Mismatch in Specification Major Version"
#endif
#if (4 != CAN_REG_H_AR_MINOR_VERSION)
    #error "Can.c:Mismatch in Specification Minor Version"
#endif

#if (2 != CAN_IRQ_H_AR_MAJOR_VERSION)
    #error "Can.c:Mismatch in Specification Major Version"
#endif
#if (4 != CAN_IRQ_H_AR_MINOR_VERSION)
    #error "Can.c:Mismatch in Specification Minor Version"
#endif

/*=======[M A C R O S]========================================================*/
/* Can support max mailbox */
#if(CAN_VARIANT_PB == CAN_VARIANT_CFG)
#define CAN_MAX_MAILBOXES_SUPPORT   CAN_HW_MAX_MAILBOXES
#else 
#define CAN_MAX_MAILBOXES_SUPPORT   CAN_MAX_HARDWAREOBJECTS
#endif /* CAN_VARIANT_PB == CAN_VARIANT_CFG */

/* DEM Report function empty */
#if (STD_OFF == CAN_DEM_ERROR_DETECT)
#define Dem_ReportErrorStatus(eventId, eventStatus)   do{}while(0)
#endif

/* MISRA RULE 19.7:3453 VIOLATION: the marco like a function */
#if(CAN_VARIANT_PB == CAN_VARIANT_CFG)
/* MISRA RULE 17.4:491 VIOLATION: Array subscripting applied to an object pointer */
#define CAN_CNTRL_CFG(controller)         (Can_GlobalConfigPtr->CanController[controller])
#define CAN_HWOBJ_CFG(mbId)               (Can_GlobalConfigPtr->CanHardwareObject[mbId])
#define CAN_HWOBJ_ID(hth)                 (Can_GlobalConfigPtr->CanHoh[hth])
#define CAN_HWOBJ_NUM                     (Can_GlobalConfigPtr->CanHardwareObjectNum)
#define CAN_HOH_NUM                       (Can_GlobalConfigPtr->CanHohNum)

#else /* CAN_VARIANT_PB == CAN_VARIANT_CFG */
#define CAN_CNTRL_CFG(controller)         (Can_ControllerConfigData[controller])
#define CAN_HWOBJ_CFG(mbId)               (Can_HardwareObjectConfigData[mbId])
#define CAN_HWOBJ_ID(hth)                 (Can_HohConfigData[hth])
#define CAN_HWOBJ_NUM                     CAN_MAX_HARDWAREOBJECTS
#define CAN_HOH_NUM                       CAN_MAX_HOHS
#endif /* CAN_VARIANT_PB == CAN_VARIANT_CFG */

/* MISRA RULE 11.3:303 VIOLATION: Hardware register address operation */
/* Contorller Register */
#define CAN_CNTRL_REG(controller) \
    ((Can_NodeRegPtrType)(Can_ControllerPCConfigData[controller].CanControllerBaseAddr))

/* Mb Register */
#define CAN_MB_REG(mb)             \
    ((Can_MbRegPtrType)(CAN_MB_BASE_ADDR + ((mb) * CAN_MB_ADDR_OFFSET)))

/* controller PC config */
#define CAN_CNTRL_PCCFG(controller)  (Can_ControllerPCConfigData[controller])

/* define interrupt line for each controller */
#define CAN_BUSOFF_INT_LINE(Controller) ((uint32)(3U*(Controller)) + 0U)
#define CAN_RX_INT_LINE(Controller)     ((uint32)(3U*(Controller)) + 1U)
#define CAN_TX_INT_LINE(Controller)     ((uint32)(3U*(Controller)) + 2U)

/* static alloc message object to list */
#define CAN_LIST_STATIC_ALLOC(list, mbId)      \
        CAN_PNCTR_REG = ((uint32)(list) << 24U) | ((uint32)(mbId) << 16U); \
        CAN_PNCTR_REG |= CAN_PANCMD_STATIC_ALLOCATE 

/* clear MSPND sepcified bit */
#define CAN_MSPND_CLEAR(mbId)  \
    do{                        \
        CAN_MSPND_REG[(mbId) >> 4U] &= ~(uint32)(0x1U << ((mbId) & 0xFU)); \
    }while(0)

/* Unlock Endinit-protected register */
#define CAN_REGISTER_UNLOCK()                           \
        Can_WriteWDTCON0(CAN_WDT_CON0 & ~CAN_WDT_CON0_ENDINIT); \
        while(0 != (CAN_WDT_CON0 & CAN_WDT_CON0_ENDINIT)){}

/* Lock Endinit-protected register */
#define CAN_REGISTER_LOCK() Can_WriteWDTCON0(CAN_WDT_CON0 | CAN_WDT_CON0_ENDINIT)

/*=======[T Y P E   D E F I N I T I O N S]====================================*/
#if(STD_ON == CAN_DEV_ERROR_DETECT)
/* Can Driver State Machine */
typedef enum
{
    CAN_UNINIT = 0,
    CAN_READY
} Can_DriverStatusType;
#endif /* STD_ON == CAN_DEV_ERROR_DETECT */

typedef enum
{
    CAN_CS_UNINT = 0U,
    CAN_CS_STOPPED,
    CAN_CS_STARTED,
    CAN_CS_SLEEP
} Can_ControllerModeType;

/* Controller Runtime Structure */
typedef struct
{
    Can_ControllerModeType  CntrlMode;      /* controller mode */
    uint32                  IntLockCount;  
} Can_ControllerStatusType;

/*=======[I N T E R N A L   D A T A]==========================================*/
#if(STD_ON == CAN_DEV_ERROR_DETECT)
/* @req <CAN103> */
/* can module status:(CAN_UNINIT, CAN_READY) */
#define CAN_START_SEC_VAR_POWER_ON_INIT_UNSPECIFIED
#include "Can_MemMap.h"
STATIC VAR(Can_DriverStatusType, CAN_VAR_POWER_ON_INIT) Can_DriverStatus = CAN_UNINIT;
#define CAN_STOP_SEC_VAR_POWER_ON_INIT_UNSPECIFIED
#include "Can_MemMap.h"
#endif /* STD_ON == CAN_DEV_ERROR_DETECT */

/* Global Config Pointer */
#define CAN_START_SEC_CONST_UNSPECIFIED
#include "Can_MemMap.h"
STATIC P2CONST(Can_ConfigType, CAN_CONST, CAN_CONST_PBCFG) Can_GlobalConfigPtr;
#define CAN_STOP_SEC_CONST_UNSPECIFIED
#include "Can_MemMap.h"

/* Controller Runtime structure */
#define CAN_START_SEC_VAR_NOINIT_UNSPECIFIED
#include "Can_MemMap.h"
STATIC VAR(Can_ControllerStatusType, CAN_VAR) Can_Cntrl[CAN_MAX_CONTROLLERS];
#define CAN_STOP_SEC_VAR_NOINIT_UNSPECIFIED
#include "Can_MemMap.h"

/* Transmit PDU handles for TxConfirmation callbacks to CANIF */
#define CAN_START_SEC_VAR_NOINIT_UNSPECIFIED
#include "Can_MemMap.h"
STATIC PduIdType Can_TxPduHandles[CAN_MAX_MAILBOXES_SUPPORT];  
#define CAN_STOP_SEC_VAR_NOINIT_UNSPECIFIED
#include "Can_MemMap.h"

/*=======[I N T E R N A L   F U N C T I O N   D E C L A R A T I O N S]========*/
#define CAN_START_SEC_CODE
#include "Can_MemMap.h"

/* Mode Control */
STATIC FUNC(Can_ReturnType, CAN_CODE) Can_StartMode(uint8 Controller);
STATIC FUNC(Can_ReturnType, CAN_CODE) Can_StopMode(uint8 Controller);
STATIC FUNC(Can_ReturnType, CAN_CODE) Can_SleepMode(uint8 Controller);
STATIC FUNC(Can_ReturnType, CAN_CODE) Can_WakeupMode(uint8 Controller);

STATIC FUNC(void, CAN_CODE) Can_InitHwCntrl
(
    uint8 Controller, 
    P2CONST(Can_ControllerConfigType, AUTOMATIC, CAN_CONST_PBCFG) Config
);
STATIC FUNC(void,    CAN_CODE)   Can_InitMB(uint8 Controller);

#if(STD_ON == CAN_HW_TRANSMIT_CANCELLATION)
STATIC FUNC(void,    CAN_CODE)   Can_TxCancel(uint8 HwObjId, uint8 Controller);
#endif /* STD_ON == CAN_HW_TRANSMIT_CANCELLATION */
#if(STD_ON == CAN_MULTIPLEXED_TRANSMISSION)
STATIC FUNC(uint8,  CAN_CODE)   Can_FindLowPriorityMb(uint8 Hth);
#endif /* STD_ON == CAN_MULTIPLEXED_TRANSMISSION */
STATIC FUNC(boolean, CAN_CODE)   Can_IsTxMbFree(uint8 HwObjId);
STATIC FUNC(void, CAN_CODE)      Can_WriteMb
(
    uint8 HwObjId, 
    P2CONST(Can_PduType, AUTOMATIC, CAN_APPL_CONST) PduInfo
);

#if ((STD_ON==CAN_HW_TRANSMIT_CANCELLATION)||(STD_ON==CAN_MULTIPLEXED_TRANSMISSION))
STATIC FUNC(uint32,  CAN_CODE)   Can_GetMBCanId(uint8 HwObjId);
#endif /* (STD_ON==CAN_HW_TRANSMIT_CANCELLATION)||(STD_ON==CAN_MULTIPLEXED_TRANSMISSION) */
STATIC FUNC(void,    CAN_CODE)   Can_GetMBInfo
(
    uint8 HwObjId, 
    P2VAR(Can_PduType, AUTOMATIC, AUTOMATIC) pdu 
);
#if ((STD_ON==CAN_HW_TRANSMIT_CANCELLATION)||(STD_ON==CAN_MULTIPLEXED_TRANSMISSION))
STATIC FUNC(boolean, CAN_CODE) Can_PriorityHigher(Can_IdType destId, Can_IdType srcId);
#endif /* (STD_ON==CAN_HW_TRANSMIT_CANCELLATION)||(STD_ON==CAN_MULTIPLEXED_TRANSMISSION) */
 
STATIC FUNC(void, CAN_CODE) Can_DisableInt(uint8 Controller);
STATIC FUNC(void, CAN_CODE) Can_StartStateEnableInt(uint8 Controller);

STATIC FUNC(void, CAN_CODE) Can_WriteWDTCON0(uint32 wdtCon0);

#if (STD_ON == CAN_TX_POLLING)
STATIC FUNC(void, CAN_CODE) Can_TxAllProcess(uint8 Controller);
#endif /* STD_ON == CAN_TX_POLLING */
#if (STD_ON == CAN_RX_POLLING)
STATIC FUNC(void, CAN_CODE) Can_RxAllProcess(uint8 Controller);
#endif /* STD_ON == CAN_RX_POLLING */
/*=======[F U N C T I O N   I M P L E M E N T A T I O N S]====================*/

/******************************************************************************/
/*
 * Brief               <This function initializes the CAN driver>
 * ServiceId           <0x00>
 * Sync/Async          <Synchronous>
 * Reentrancy          <Non Reentrant>
 * Param-Name[in]      <Config:Pointer to driver configuration>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
FUNC(void, CAN_CODE) Can_Init
(
    P2CONST(Can_ConfigType, AUTOMATIC, CAN_CONST_PBCFG) Config
)
{
    uint8  controller = 0U;
    uint32 regValue   = 0U;
    uint32 timeOut    = 0U;
 
    #if(STD_ON == CAN_DEV_ERROR_DETECT)
    if(CAN_UNINIT != Can_DriverStatus) /* @req <CAN174> @req <CAN247> */
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, CAN_INIT_ID, CAN_E_TRANSITION);
    }
    #if(CAN_VARIANT_PB == CAN_VARIANT_CFG)   
    else if(NULL_PTR == Config)        /* @req <CAN175> */
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, CAN_INIT_ID, CAN_E_PARAM_POINTER);
    }
    #endif /* CAN_VARIANT_PB == CAN_VARIANT_CFG */
    else
    #endif /* STD_ON == CAN_DEV_ERROR_DETECT */
    {
        /* backup config pointer */
        #if(CAN_VARIANT_PB == CAN_VARIANT_CFG)   
        Can_GlobalConfigPtr = Config;
        #endif /* #if(CAN_VARIANT_PB == CAN_VARIANT_CFG) */

        /*@req <CAN245> init runntiming data of each controller */
        for(controller = 0U; controller < CAN_MAX_CONTROLLERS; controller++)
        {
            Can_Cntrl[controller].IntLockCount    = 0U;
            Can_Cntrl[controller].CntrlMode       = CAN_CS_STOPPED; /* @req <CAN259> */
        }

        timeOut = CAN_TIMEOUT_DURATION;

        CAN_REGISTER_UNLOCK();
        /* Enable Can module */
        CAN_CLC_REG = CAN_ENABLE_MODULE;
        while((timeOut > 0U) && (CAN_DISABLE_STATE == (CAN_CLC_REG & CAN_DISABLE_STATE)))
        {
            timeOut--;
        }
        CAN_REGISTER_LOCK();

        if(0U == timeOut)
        {
            Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED);
        }                
        else
        {
            /* Set Divder */
            CAN_REGISTER_UNLOCK();
            CAN_FDR_REG = (uint32)(CAN_FDR_DM_NORMAL | CAN_STEP);
            /* Dummy read to avoid pipeline effects */
            regValue = CAN_FDR_REG;
            CAN_REGISTER_LOCK();

            /* set clock source */
            CAN_MCR_REG = CAN_MCR_REG_VALUE;
            /* initialize lists */
            CAN_PNCTR_REG = CAN_PANCMD_INIT;
            timeOut = CAN_TIMEOUT_DURATION;
            while((timeOut > 0U) && (CAN_PNCTR_BUSY == (CAN_PNCTR_REG & CAN_PNCTR_BUSY)))
            {
                timeOut--;
            }

            if(0U == timeOut)
            {
                Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED);
            }                

            else 
            {
                /* @req <CAN246> */
                #if (STD_ON == CAN_DEV_ERROR_DETECT)
                Can_DriverStatus = CAN_READY;  
                #endif /* STD_ON == CAN_DEV_ERROR_DETECT */
            }
        }
    }
    
    return;
}

/******************************************************************************/
/*
 * Brief               <This function initializing only Can controller specific settings>
 * ServiceId           <0x02>
 * Sync/Async          <Synchronous>
 * Reentrancy          <Non Reentrant>
 * Param-Name[in]      <Controller-CAN controller to be initialized>
 * Param-Name[out]     <Config-pointer to controller configuration>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
FUNC(void, CAN_CODE) Can_InitController
(
    uint8 Controller,
    P2CONST(Can_ControllerConfigType, AUTOMATIC, CAN_CONST_PBCFG) Config
)
{
    #if(STD_ON == CAN_DEV_ERROR_DETECT)
    if(CAN_READY != Can_DriverStatus)  /* @req <CAN187> */
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, CAN_INITCONTROLLER_ID, CAN_E_UNINIT);
    }
    else if(NULL_PTR == Config)        /* @req <CAN188> */
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, CAN_INITCONTROLLER_ID, CAN_E_PARAM_POINTER);
    }
    else if(Controller >= CAN_MAX_CONTROLLERS) /* @req <CAN189> */
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, CAN_INITCONTROLLER_ID, 
                CAN_E_PARAM_CONTROLLER);
    }
    else if(CAN_CS_STOPPED != Can_Cntrl[Controller].CntrlMode) /* @req <CAN190> */
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, CAN_INITCONTROLLER_ID, CAN_E_TRANSITION);
    }
    else
    #endif /* STD_ON == CAN_DEV_ERROR_DETECT */   
    {
        Can_InitHwCntrl(Controller, Config);

        Can_Cntrl[Controller].CntrlMode = CAN_CS_STOPPED;  /* @req <CAN256> */
    }
    
    return;
}

/******************************************************************************/
/*
 * Brief               <This function performs software triggered state transitions 
 *                         of the CAN controller State machine.>
 * ServiceId           <0x03>
 * Sync/Async          <Asynchronous>
 * Reentrancy          <Non Reentrant>
 * Param-Name[in]      <Controller-CAN controller for which the status shall be changed>
 * Param-Name[in]      <Transition-Possible transitions>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <Can_ReturnType-CAN_OK or CAN_NOT_OK>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
/*@req <CAN230> @req <CAN017> */
FUNC(Can_ReturnType, CAN_CODE) Can_SetControllerMode
(
    uint8 Controller,
    Can_StateTransitionType Transition
)
{
    Can_ReturnType ret = CAN_NOT_OK;

    #if(STD_ON == CAN_DEV_ERROR_DETECT)
    if(CAN_READY != Can_DriverStatus)          /* @req <CAN0198> */
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, CAN_SETCONTROLLERMODE_ID, CAN_E_UNINIT);
        ret = CAN_NOT_OK;
    }
    else if(Controller >= CAN_MAX_CONTROLLERS) /* @req <CAN0199> */
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 
                CAN_SETCONTROLLERMODE_ID, CAN_E_PARAM_CONTROLLER);
        ret = CAN_NOT_OK;
    }    
    /* @req <CAN0200> */
    else if(Transition >= CAN_T_CNT)
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, CAN_SETCONTROLLERMODE_ID, CAN_E_TRANSITION);
        ret = CAN_NOT_OK;
    }
    else
    #endif /* STD_ON == CAN_DEV_ERROR_DETECT */
    {
        switch (Transition)
        {
            case CAN_T_START:
                ret = Can_StartMode(Controller);
                break;
            case CAN_T_STOP:
                ret = Can_StopMode(Controller);
                break;
            case CAN_T_SLEEP:
                ret = Can_SleepMode(Controller);
                break;
            case CAN_T_WAKEUP:
                ret = Can_WakeupMode(Controller);
                break;
            default:
                ret = CAN_NOT_OK;
                break;
        }
    }

    return ret;
}

/******************************************************************************/
/*
 * Brief               <This function disable all interrupt for this controller. >
 * ServiceId           <0x04>
 * Sync/Async          <Synchronous>
 * Reentrancy          <Reentrant>
 * Param-Name[in]      <Controller- CAN controller for which interrupts shall be disabled>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
/*@req <CAN0231>*/
FUNC(void, CAN_CODE) Can_DisableControllerInterrupts(uint8 Controller)
{
    /*@req <CAN0205>*/
    /*@req <CAN0206>*/
    #if(STD_ON == CAN_DEV_ERROR_DETECT)
    if(CAN_READY != Can_DriverStatus)
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 
                CAN_DISABLECONTROLLERINTERRUPTS_ID, CAN_E_UNINIT);
    }
    else if(Controller >= CAN_MAX_CONTROLLERS)
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 
                CAN_DISABLECONTROLLERINTERRUPTS_ID, CAN_E_PARAM_CONTROLLER);
    }
    else
    #endif /* STD_ON == CAN_DEV_ERROR_DETECT */
    {
        SchM_Enter_Can(CAN_INSTANCE, INTERRUPT_PROTECTION_AREA);

        /* Disable interrupt */
        Can_DisableInt(Controller);

        Can_Cntrl[Controller].IntLockCount++;

        SchM_Exit_Can(CAN_INSTANCE, INTERRUPT_PROTECTION_AREA);             
    }

    return;
}

/******************************************************************************/
/*
 * Brief               <This function enable all allowed interrupts. >
 * ServiceId           <0x05>
 * Sync/Async          <Synchronous>
 * Reentrancy          <Reentrant>
 * Param-Name[in]      <Controller- CAN controller for which interrupts shall be disabled>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
/* @req <CAN0232> @req <CAN050> */
FUNC(void, CAN_CODE)  Can_EnableControllerInterrupts(uint8 Controller)
{
    /*@req <CAN0209>*/
    /*@req <CAN0210>*/
    #if(STD_ON == CAN_DEV_ERROR_DETECT)
    if(CAN_READY != Can_DriverStatus)
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 
                CAN_ENABLECONTROLLERINTERRUPTS_ID, CAN_E_UNINIT);
    }
    else if(Controller >= CAN_MAX_CONTROLLERS)
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 
                CAN_ENABLECONTROLLERINTERRUPTS_ID, CAN_E_PARAM_CONTROLLER);
    }
    else
    #endif /* STD_ON == CAN_DEV_ERROR_DETECT */   
    {
        if (CAN_CS_STARTED == Can_Cntrl[Controller].CntrlMode)
        {
            SchM_Enter_Can(CAN_INSTANCE, INTERRUPT_PROTECTION_AREA);

            /* @req <CAN0209> enable interrupt call before disable interrupt no action */
            if(Can_Cntrl[Controller].IntLockCount > 0U)
            {
                Can_Cntrl[Controller].IntLockCount--;

                if(0U == Can_Cntrl[Controller].IntLockCount)
                {
                    Can_StartStateEnableInt(Controller);
                }
            }

            SchM_Exit_Can(CAN_INSTANCE, INTERRUPT_PROTECTION_AREA);             
        }
    }

    return;
}

/******************************************************************************/
/*
 * Brief               <This function perform HW-Transmit handle transmit. >
 * ServiceId           <0x06>
 * Sync/Async          <Synchronous>
 * Reentrancy          <Reentrant>
 * Param-Name[in]      <Hth-information which HW-transmit handle shall be used for transmit.>
 * Param-Name[in]      <PduInfo-Pointer to SDU user memory,DLC and Identifier>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <Can_ReturnType-Returns CAN_OK,CAN_NOT_OK or CAN_BUSY>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
/* @req <CAN276> @req <CAN0233> @req <CAN0212> @req <CAN0275> */
FUNC(Can_ReturnType, CAN_CODE) Can_Write
(
    uint8 Hth,
    P2CONST(Can_PduType, AUTOMATIC, CAN_APPL_DATA) PduInfo
)
{
    Can_ReturnType ret = CAN_NOT_OK;
    uint8 controller = 0U;
    uint8 hwObjId    = 0U;
    
    #if(STD_ON == CAN_DEV_ERROR_DETECT)
    boolean errFlag = FALSE;

    if(CAN_READY != Can_DriverStatus)
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, CAN_WRITE_ID, CAN_E_UNINIT);
        errFlag = TRUE;
        ret = CAN_NOT_OK;
    }
    /* check hth is vaild */
    else if((Hth >= CAN_HOH_NUM) 
            || (CAN_OBJECT_TYPE_TRANSMIT != CAN_HWOBJ_CFG(CAN_HWOBJ_ID(Hth)).CanObjectType)) 
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, CAN_WRITE_ID, CAN_E_PARAM_HANDLE);
        errFlag = TRUE;
        ret = CAN_NOT_OK;
    }
    else if((NULL_PTR == PduInfo) || (NULL_PTR == PduInfo->sdu))
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, CAN_WRITE_ID, CAN_E_PARAM_POINTER);
        errFlag = TRUE;
        ret = CAN_NOT_OK;
    }
    else if(CAN_DATA_LENGTH < PduInfo->length)
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, CAN_WRITE_ID, CAN_E_PARAM_DLC);
        errFlag = TRUE;
        ret = CAN_NOT_OK;
    }
    else
    {
        /* do nothing */
    }
    if (FALSE == errFlag)
    #endif /* STD_ON == CAN_DEV_ERROR_DETECT */                    
    {
        hwObjId = CAN_HWOBJ_ID(Hth);
        controller = CAN_HWOBJ_CFG(hwObjId).CanControllerRef;

        if (CAN_CS_STARTED == Can_Cntrl[controller].CntrlMode)
        {
            #if(STD_ON == CAN_MULTIPLEXED_TRANSMISSION)
            hwObjId = Can_FindLowPriorityMb(Hth);
            #endif /* STD_ON == CAN_MULTIPLEXED_TRANSMISSION */

            if (TRUE == Can_IsTxMbFree(hwObjId))
            {
                Can_WriteMb(hwObjId, PduInfo);
                ret = CAN_OK;
            }
            else 
            {
                #if(STD_ON == CAN_HW_TRANSMIT_CANCELLATION)
                if (TRUE == Can_PriorityHigher(PduInfo->id, Can_GetMBCanId(hwObjId)))
                {
                    Can_TxCancel(hwObjId, controller);
                }
                #endif /* STD_ON == CAN_HW_TRANSMIT_CANCELLATION */

                ret = CAN_BUSY;
            }
        }
    }
    return ret;    
}

/******************************************************************************/
/*
 * Brief               <This function checks if a wakeup has occurred for the given controller. >
 * ServiceId           <0x0b>
 * Sync/Async          <Synchronous>
 * Reentrancy          <Non Reentrant>
 * Param-Name[in]      <Controller- Controller to be checked for a wakeup>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <Std_ReturnType- Returns-E_OK or E_NOT_OK>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
FUNC(Std_ReturnType, CAN_CODE) Can_Cbk_CheckWakeup(uint8 Controller)
{
    #if(STD_ON == CAN_WAKEUP_SUPPORT)

    Std_ReturnType ret = E_NOT_OK;

     /*@req <CAN362>*/
    #if(STD_ON == CAN_DEV_ERROR_DETECT)
    if(CAN_READY != Can_DriverStatus)
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, CAN_CBK_CHECKWAKEUP_ID, CAN_E_UNINIT);
        ret = E_NOT_OK;
    }
    /*@req <CAN363>*/
    else if(Controller >= CAN_MAX_CONTROLLERS)
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, 
                CAN_CBK_CHECKWAKEUP_ID, CAN_E_PARAM_CONTROLLER);
        ret = E_NOT_OK;
    } 
    else
    #endif /* STD_ON == CAN_DEV_ERROR_DETECT */
    {
        ret = E_OK;
    }
    
    return ret;
    #else
    Controller = Controller;
    return E_NOT_OK;
    #endif /* STD_ON == CAN_WAKEUP_SUPPORT */
}

/******************************************************************************/
/*
 * Brief               <This function performs the polling of TX confirmation and TX cancellation 
 *                          confirmation when.CAN_TX_PROCESSING is set to POLLING. >
 * ServiceId           <0x01>
 * Param-Name[in]      <None>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/

/* @req <CAN0225> @req <CAN031> */
FUNC(void, CAN_CODE) Can_MainFunction_Write(void)
{
    #if (STD_ON == CAN_TX_POLLING)
    uint8 Controller;

    /*@req <CAN179>*/
    #if(STD_ON == CAN_DEV_ERROR_DETECT)
    /*@req <CAN187>*/
    if(CAN_READY != Can_DriverStatus)
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, CAN_MAINFUCTION_WRITE_ID, CAN_E_UNINIT);
    }
    else
    #endif /* STD_ON == CAN_DEV_ERROR_DETECT */
    {
        /* loop each Controller TX comfirmation and TX cancel comfirmation */
        for (Controller = 0U; Controller < CAN_MAX_CONTROLLERS; Controller++)
        {
            /*@req <CAN178>*/
            if((CAN_PROCESS_TYPE_POLLING == CAN_CNTRL_PCCFG(Controller).CanTxProcessing)
                    && (CAN_CS_STARTED == Can_Cntrl[Controller].CntrlMode))
            {
                Can_TxAllProcess(Controller);
            }
        }
    }
    #endif /* STD_ON == CAN_TX_POLLING */

    return;
}

/******************************************************************************/
/*
 * Brief               <This function performs the polling of RX indications when 
 *                          CAN_RX_PROCESSING is set to POLLING.> 
 * ServiceId           <0x08>
 * Param-Name[in]      <None>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
 /*@req <CAN012>
[heguarantee that neither the ISRs 
 nor the function Can_MainFunction_Read can be interrupted by itself. ]
*/
/* @req <CAN226> @req <CAN108> @req <CAN180> */
FUNC(void, CAN_CODE) Can_MainFunction_Read(void)
{
    #if (STD_ON == CAN_RX_POLLING)
    uint8 controller;

    /*@req <CAN181>*/
    #if(STD_ON == CAN_DEV_ERROR_DETECT)
    /*@req <CAN187>*/
    if(CAN_READY != Can_DriverStatus)
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, CAN_MAINFUNCTION_READ_ID, CAN_E_UNINIT);
    }
    else
    #endif /* STD_ON == CAN_DEV_ERROR_DETECT */    
    {
        /* scan each Controller */
        for (controller = 0U; controller < CAN_MAX_CONTROLLERS; controller++)
        {
            if((CAN_PROCESS_TYPE_POLLING == CAN_CNTRL_PCCFG(controller).CanRxProcessing)
                    && (CAN_CS_STARTED == Can_Cntrl[controller].CntrlMode))
            {
                Can_RxAllProcess(controller);
            }
        }        
    }
    #endif /* STD_ON == CAN_RX_POLLING */

    return;
}

/******************************************************************************/
/*
 * Brief               <This function performs the polling of bus-off events that are configured
 *                          statically as "to be polled".> 
 * ServiceId           <0x09>
 * Param-Name[in]      <None>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
FUNC(void, CAN_CODE) Can_MainFunction_BusOff(void)
{
    #if (STD_ON == CAN_BUSOFF_POLLING)
    uint8 controller;

    #if(STD_ON == CAN_DEV_ERROR_DETECT)
    if(CAN_READY != Can_DriverStatus)  /* @req <CAN184> */
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, CAN_MAINFUNCTION_BUSOFF_ID, CAN_E_UNINIT);
    }
    else
    #endif /* STD_ON == CAN_DEV_ERROR_DETECT */  
    {
        for (controller = 0U; controller < CAN_MAX_CONTROLLERS; controller++)
        {
            if((CAN_PROCESS_TYPE_POLLING == CAN_CNTRL_PCCFG(controller).CanBusOffProcessing)
                    && (CAN_CS_STARTED == Can_Cntrl[controller].CntrlMode))
            {
                Can_BusOff_Handler(controller);
            }
        }       
    }
    #endif /* STD_ON == CAN_BUSOFF_POLLING */

    return;
}

/******************************************************************************/
/*
 * Brief               <This function performs the polling of wake-up events that are configured
 *                          statically as "to be polled".> 
 * ServiceId           <0x0a>
 * Param-Name[in]      <None>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
FUNC(void, CAN_CODE) Can_MainFunction_Wakeup(void)
{
    #if(STD_ON == CAN_WAKEUP_SUPPORT)

    #if(STD_ON == CAN_DEV_ERROR_DETECT)
    /*@req <CAN184>*/
    if(CAN_READY != Can_DriverStatus)
    {
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, CAN_MAINFUNCTION_WAKEUP_ID, CAN_E_UNINIT);
    }
    #endif /* STD_ON == CAN_DEV_ERROR_DETECT */

    #endif /* (STD_ON == CAN_WAKEUP_POLLING) && (STD_ON == CAN_WAKEUP_SUPPORT) */

    return;
}

/*=======[I N T E R N A L  F U N C T I O N   I M P L E M E N T A T I O N S]====================*/
/******************************************************************************/
/*
 * Brief               <This function performs bus-off  process>
 * Param-Name[in]      <Controller- CAN controller to be Tw/Rw/bus-off process>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
FUNC(void, CAN_CODE) Can_BusOff_Handler(uint8 Controller)
{
    Can_NodeRegPtrType canRegs;
    Can_ReturnType ret_val = CAN_NOT_OK;

    canRegs = CAN_CNTRL_REG(Controller);

    if (CAN_NSR_ALERT == (canRegs->Nsr & CAN_NSR_ALERT))     /* ALERT */
    {
        if (CAN_NSR_BOFF == (canRegs->Nsr & CAN_NSR_BOFF))   /* BUSOFF */
        {
            ret_val = Can_StopMode(Controller);
            if(CAN_OK == ret_val)
            {
                CanIf_ControllerBusOff(Controller);
            }
        }
        else if (CAN_NSR_EWRN == (canRegs->Nsr & CAN_NSR_EWRN)) /* EWRN */
        {
            /* call upper indications callbacks */
        }
        else if (CAN_NCR_INIT == (canRegs->Ncr & CAN_NCR_INIT)) /* EWRN */
        {
            canRegs->Ncr &= CAN_NCR_INIT_CLEAR;
        }
        else
        {
            /* do noting */
        }

        canRegs->Nsr &= CAN_NSR_ALERT_CLEAR;
    }
    else if (0U != (canRegs->Nsr & CAN_NSR_LEC))               /* LEC */
    {
        canRegs->Nsr &= CAN_NSR_LEC_CLEAR;

        /* Active Error: REC < 128U & TEC < 128U */
        if (((canRegs->Necnt & CAN_NECNT_REC) < 128U) 
                && (((canRegs->Necnt & CAN_NECNT_TEC) >> 8U) < 128U))
        {
            /* call upper indications callbacks */   
        } 
    }
    else
    {
        /* do nothing */
    }

    return;
}

/******************************************************************************/
/*
 * Brief               <This function performs Tx confirmation and Tx cancellation process>
 * Param-Name[in]      <Controller- CAN controller to be Tx process>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
FUNC(void, CAN_CODE) Can_TxProcess(uint8 Controller)
{
    Can_NodeRegPtrType canRegs;
    Can_MbRegPtrType   mbRegs;
    uint8 hwObjId    = 0U;
    uint8 endHwObjId = 0U;

    canRegs = CAN_CNTRL_REG(Controller);
 
    if ((canRegs->Nsr & CAN_TX_OK) == CAN_TX_OK)
    {
        /* Clear tx successful flag */
        canRegs->Nsr &= ~CAN_TX_OK;

        endHwObjId = (uint8)(CAN_CNTRL_CFG(Controller).CanTxHwObjFirst
                              + CAN_CNTRL_CFG(Controller).CanTxHwObjCount);
        for (hwObjId = CAN_CNTRL_CFG(Controller).CanTxHwObjFirst; hwObjId < endHwObjId; hwObjId++)
        {
            mbRegs = CAN_MB_REG(hwObjId);
            if ((mbRegs->Mctstr & CAN_MB_TX_MASK) == CAN_MB_TX_MASK)
            {
                /* Clear new data flag */
                mbRegs->Mctstr = CAN_RES_NEWDAT_MASK;

                /* Reset TXPND */
                mbRegs->Mctstr = CAN_MB_TX_MASK;

                /* Reset MSGVAL */
                mbRegs->Mctstr = CAN_RES_MSGVAL;

                /* Reset PND bit */
                CAN_MSPND_CLEAR(hwObjId);

                CanIf_TxConfirmation(Can_TxPduHandles[hwObjId]);

                break;
            }
            else
            {
                /* Reset PND bit */
                CAN_MSPND_CLEAR(hwObjId);
            }
        }
    }

    return;
}

/******************************************************************************/
/*
 * Brief               <This function performs Rx indications  process>
 * Param-Name[in]      <Controller- CAN controller to be Rx process>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
FUNC(void, CAN_CODE) Can_RxProcess(uint8 Controller)
{
    Can_NodeRegPtrType canRegs;
    Can_MbRegPtrType mbRegs;
    uint8 hwObjId    = 0U;
    uint8 endHwObjId = 0U;
    uint8 rxData[8];
    Can_PduType pdu;

    canRegs = CAN_CNTRL_REG(Controller);

    if ((canRegs->Nsr & CAN_RX_OK) == CAN_RX_OK)
    {
        /* Clear tx successful flag */
        canRegs->Nsr &= ~CAN_RX_OK;

        endHwObjId = (uint8)(CAN_CNTRL_CFG(Controller).CanRxHwObjFirst
                              + CAN_CNTRL_CFG(Controller).CanRxHwObjCount);
        for (hwObjId = CAN_CNTRL_CFG(Controller).CanRxHwObjFirst; hwObjId < endHwObjId; hwObjId++)
        {
            mbRegs = CAN_MB_REG(hwObjId);
            if ((mbRegs->Mctstr & CAN_MB_RX_MASK) == CAN_MB_RX_MASK)
            {
                if ((mbRegs->Mctstr & CAN_RES_NEWDAT_MASK) == CAN_RES_NEWDAT_MASK)
                {
                    /* Message has lost */
                    if ((mbRegs->Mctstr & CAN_RES_MSGLST_MASK) == CAN_RES_MSGLST_MASK)
                    {
                        /* Reset MSGLST bit */
                        mbRegs->Mctstr = CAN_RES_MSGLST_MASK;
                    }
                    /* Get pdu */
                    pdu.sdu = rxData;
                    Can_GetMBInfo(hwObjId, &pdu);

                    /* Reset PND bit */
                    CAN_MSPND_CLEAR(hwObjId);

                    CanIf_RxIndication(CAN_HWOBJ_CFG(hwObjId).CanObjectId, pdu.id, pdu.length, pdu.sdu);

                    /* Rest NEWDAT bit */
                    mbRegs->Mctstr = CAN_RES_NEWDAT_MASK;

                    mbRegs->Mctstr = CAN_RX_OK;
                    break;
                }
                mbRegs->Mctstr = CAN_RX_OK;
            }
            else
            {
                /* Reset PND bit */
                CAN_MSPND_CLEAR(hwObjId);
            }
        }
    }
    return;
}

#if (STD_ON == CAN_TX_POLLING)
/******************************************************************************/
/*
 * Brief               <This function performs Tx confirmation and Tx cancellation
 *                      process for all mailboxes>
 * Param-Name[in]      <Controller- CAN controller to be Tx process>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
STATIC FUNC(void, CAN_CODE) Can_TxAllProcess(uint8 Controller)
{
    Can_NodeRegPtrType canRegs;
    Can_MbRegPtrType   mbRegs;
    uint8 hwObjId    = 0U;
    uint8 endHwObjId = 0U;

    canRegs = CAN_CNTRL_REG(Controller);
 
    if ((canRegs->Nsr & CAN_TX_OK) == CAN_TX_OK)
    {
        /* Clear tx successful flag */
        canRegs->Nsr &= ~CAN_TX_OK;

        endHwObjId = (uint8)(CAN_CNTRL_CFG(Controller).CanTxHwObjFirst
                              + CAN_CNTRL_CFG(Controller).CanTxHwObjCount);
        for (hwObjId = CAN_CNTRL_CFG(Controller).CanTxHwObjFirst; hwObjId < endHwObjId; hwObjId++)
        {
            mbRegs = CAN_MB_REG(hwObjId);
            if ((mbRegs->Mctstr & CAN_MB_TX_MASK) == CAN_MB_TX_MASK)
            {
                /* Clear new data flag */
                mbRegs->Mctstr = CAN_RES_NEWDAT_MASK;

                /* Reset TXPND */
                mbRegs->Mctstr = CAN_MB_TX_MASK;

                /* Reset MSGVAL */
                mbRegs->Mctstr = CAN_RES_MSGVAL;

                /* Reset PND bit */
                CAN_MSPND_CLEAR(hwObjId);

                CanIf_TxConfirmation(Can_TxPduHandles[hwObjId]);
            }
            else
            {
                /* Reset PND bit */
                CAN_MSPND_CLEAR(hwObjId);
            }
        }
    }

    return;
}
#endif /* STD_ON == CAN_TX_POLLING */

#if (STD_ON == CAN_RX_POLLING)
/******************************************************************************/
/*
 * Brief               <This function performs Rx indications process for all mailboxes>
 * Param-Name[in]      <Controller- CAN controller to be Rx process>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
STATIC FUNC(void, CAN_CODE) Can_RxAllProcess(uint8 Controller)
{
    Can_NodeRegPtrType canRegs;
    Can_MbRegPtrType mbRegs;
    uint8 hwObjId    = 0U;
    uint8 endHwObjId = 0U;
    uint8 rxData[8];
    Can_PduType pdu;

    canRegs = CAN_CNTRL_REG(Controller);

    if ((canRegs->Nsr & CAN_RX_OK) == CAN_RX_OK)
    {
        /* Clear tx successful flag */
        canRegs->Nsr &= ~CAN_RX_OK;

        endHwObjId = (uint8)(CAN_CNTRL_CFG(Controller).CanRxHwObjFirst
                              + CAN_CNTRL_CFG(Controller).CanRxHwObjCount);
        for (hwObjId = CAN_CNTRL_CFG(Controller).CanRxHwObjFirst; hwObjId < endHwObjId; hwObjId++)
        {
            mbRegs = CAN_MB_REG(hwObjId);
            if ((mbRegs->Mctstr & CAN_MB_RX_MASK) == CAN_MB_RX_MASK)
            {
                if ((mbRegs->Mctstr & CAN_RES_NEWDAT_MASK) == CAN_RES_NEWDAT_MASK)
                {
                    /* Message has lost */
                    if ((mbRegs->Mctstr & CAN_RES_MSGLST_MASK) == CAN_RES_MSGLST_MASK)
                    {
                        /* Reset MSGLST bit */
                        mbRegs->Mctstr = CAN_RES_MSGLST_MASK;
                    }
                    /* Get pdu */
                    pdu.sdu = rxData;
                    Can_GetMBInfo(hwObjId, &pdu);

                    /* Reset PND bit */
                    CAN_MSPND_CLEAR(hwObjId);

                    CanIf_RxIndication(CAN_HWOBJ_CFG(hwObjId).CanObjectId, pdu.id, pdu.length, pdu.sdu);

                    /* Rest NEWDAT bit */
                    mbRegs->Mctstr = CAN_RES_NEWDAT_MASK;
                }
                mbRegs->Mctstr = CAN_RX_OK;
            }
            else
            {
                /* Reset PND bit */
                CAN_MSPND_CLEAR(hwObjId);
            }
        }
    }
    return;
}
#endif /* STD_ON == CAN_RX_POLLING */

#if(STD_ON == CAN_HW_TRANSMIT_CANCELLATION)
/******************************************************************************/
/*
 * Brief               <This function performs Tx cancellation process>
 * Param-Name[in]      <Controller- CAN controller to be Tx process>
 * Param-Name[in]      <mbId- CAN controller message buffer index>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
STATIC FUNC(void, CAN_CODE) Can_TxCancel(uint8 HwObjId, uint8 Controller)
{
    Can_MbRegPtrType mbRegs;
    uint8  txData[8];
    Can_PduType pdu;

    /* Mb address */
    mbRegs = CAN_MB_REG(HwObjId);

    /* Cancel transmit */
    mbRegs->Mctstr = CAN_RES_MSGVAL;

    pdu.sdu = txData;
    Can_GetMBInfo(HwObjId, &pdu);
    pdu.swPduHandle = Can_TxPduHandles[HwObjId];
    
    /* clear abort flag */
    CanIf_CancelTxConfirmation(&pdu);

    return;
}
#endif /* STD_ON == CAN_HW_TRANSMIT_CANCELLATION */

/******************************************************************************/
/*
 * Brief               <This function performs controller start Mode  process>
 * Param-Name[in]      <Controller- CAN controller to be Mode process>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
/* @req <CAN261> */
STATIC FUNC(Can_ReturnType, CAN_CODE) Can_StartMode(uint8 Controller)
{
    Can_NodeRegPtrType canRegs;
    Can_ReturnType ret = CAN_NOT_OK;
    Can_MbRegPtrType mbRegs;
    uint8 hwObjId;
    uint8 endHwObj;

    if (CAN_CS_STARTED == Can_Cntrl[Controller].CntrlMode)
    {
        ret = CAN_OK;
    }
    else if(CAN_CS_STOPPED == Can_Cntrl[Controller].CntrlMode)  
    {
        canRegs = CAN_CNTRL_REG(Controller);

        /* 
         * Enabel Rx/Tx/Busoff interrupt, set interrupt pointer  
         */
        if (0 == Can_Cntrl[Controller].IntLockCount)
        {
            Can_StartStateEnableInt(Controller);
        }
        /* goto normal mode */
        canRegs->Ncr &= CAN_SET_START_MODE;
        Can_Cntrl[Controller].CntrlMode = CAN_CS_STARTED;
        
        endHwObj = (uint8)(CAN_CNTRL_CFG(Controller).CanRxHwObjFirst
                              + CAN_CNTRL_CFG(Controller).CanRxHwObjCount);
        for (hwObjId = CAN_CNTRL_CFG(Controller).CanRxHwObjFirst; hwObjId < endHwObj; hwObjId++)
        {
            mbRegs = CAN_MB_REG(hwObjId);
            mbRegs->Mctstr = CAN_MSG_VALID;
        }

        ret = CAN_OK;
    }
    else
    {
        #if(STD_ON == CAN_DEV_ERROR_DETECT)
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, CAN_SETCONTROLLERMODE_ID, CAN_E_TRANSITION);
        #endif
        ret = CAN_NOT_OK;
    }

    return ret;
}

/******************************************************************************/
/*
 * Brief               <This function performs controller stop Mode  process>
 * Param-Name[in]      <Controller- CAN controller to be Mode process>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
/* @req <CAN283> */
STATIC FUNC(Can_ReturnType, CAN_CODE) Can_StopMode(uint8 Controller)
{
    Can_NodeRegPtrType canRegs;
    Can_ReturnType ret = CAN_NOT_OK;
    Can_MbRegPtrType mbRegs;
    uint8 mbIndex = 0U;
    uint8 endHwObj = 0u;

    if (CAN_CS_STOPPED == Can_Cntrl[Controller].CntrlMode)
    {
        ret = CAN_OK;
    }
    else if(CAN_CS_STARTED == Can_Cntrl[Controller].CntrlMode)  
    {
        canRegs = CAN_CNTRL_REG(Controller);

        /* goto normal mode */
        canRegs->Ncr |= CAN_SET_STOP_MODE;

        /* Disable interrupt */
        Can_DisableInt(Controller);

        /* Clear tx successful flag */
        canRegs->Nsr &= ~CAN_RX_OK;

        endHwObj = (uint8)(CAN_CNTRL_CFG(Controller).CanRxHwObjFirst
                              + CAN_CNTRL_CFG(Controller).CanRxHwObjCount);
        for (mbIndex = CAN_CNTRL_CFG(Controller).CanRxHwObjFirst; mbIndex < endHwObj; mbIndex++)
        {
            mbRegs = CAN_MB_REG(mbIndex);
            mbRegs->Mctstr = CAN_MSG_INVALID;
        }

        endHwObj = (uint8)(CAN_CNTRL_CFG(Controller).CanTxHwObjFirst
                                   + CAN_CNTRL_CFG(Controller).CanTxHwObjCount);
  		 for (mbIndex = CAN_CNTRL_CFG(Controller).CanTxHwObjFirst; mbIndex < endHwObj; mbIndex++)
  		 {
  			 mbRegs = CAN_MB_REG(mbIndex);
  			 mbRegs->Mctstr = CAN_MSG_INVALID;
  		 }
  		 
        Can_Cntrl[Controller].CntrlMode = CAN_CS_STOPPED;
        ret = CAN_OK;
    }
    else
    {
        #if(STD_ON == CAN_DEV_ERROR_DETECT)
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, CAN_SETCONTROLLERMODE_ID, CAN_E_TRANSITION);
        #endif
        ret = CAN_NOT_OK;
    } 
    return ret;
}

/******************************************************************************/
/*
 * Brief               <This function performs controller sleep Mode  process>
 * Param-Name[in]      <Controller- CAN controller to be Mode process>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
/* @req <CAN265> */
STATIC FUNC(Can_ReturnType, CAN_CODE) Can_SleepMode(uint8 Controller)
{
    Can_ReturnType ret = CAN_NOT_OK;

    /* Don't Support sleep & wakeup in MPC5602D */
    if (CAN_CS_SLEEP == Can_Cntrl[Controller].CntrlMode)
    {
        ret = CAN_OK;
    }
    else if(CAN_CS_STOPPED == Can_Cntrl[Controller].CntrlMode)  
    {
        ret = CAN_OK;
    }
    else
    {
        #if(STD_ON == CAN_DEV_ERROR_DETECT)
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, CAN_SETCONTROLLERMODE_ID, CAN_E_TRANSITION);
        #endif
        ret = CAN_NOT_OK;
    }
    return ret;
}

/******************************************************************************/
/*
 * Brief               <This function performs controller wakeup Mode  process>
 * Param-Name[in]      <Controller- CAN controller to be Mode process>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
STATIC FUNC(Can_ReturnType, CAN_CODE) Can_WakeupMode(uint8 Controller)
{
    Can_ReturnType ret = CAN_NOT_OK;

    /*  Don't Support Sleep & Wakeup in MPC5602D */
    if (CAN_CS_STOPPED == Can_Cntrl[Controller].CntrlMode)
    {
        ret = CAN_OK;
    }
    else
    {
        #if(STD_ON == CAN_DEV_ERROR_DETECT)
        Det_ReportError(CAN_MODULE_ID, CAN_INSTANCE, CAN_SETCONTROLLERMODE_ID, CAN_E_TRANSITION);
        #endif
        ret = CAN_NOT_OK;
    }

    return ret;
}

/******************************************************************************/
/*
 * Brief               <This function performs controller wakeup Mode  process>
 * Param-Name[in]      <Controller- CAN controller to be Mode process>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
STATIC FUNC(void, CAN_CODE) Can_InitHwCntrl
(
    uint8 Controller, 
    P2CONST(Can_ControllerConfigType, AUTOMATIC, CAN_CONST_PBCFG) Config
)
{
    Can_NodeRegPtrType canRegs;
    uint8 realController = CAN_CNTRL_PCCFG(Controller).CanControllerRelId;

    canRegs = CAN_CNTRL_REG(Controller);

    /* Terminates the participation of this node in the CAN traffic */
    canRegs->Ncr = CAN_NODE_DISABLE;

    /* set controller interrupt line */
    canRegs->Nipr = 0x0U;
    if (CAN_PROCESS_TYPE_INTERRUPT == CAN_CNTRL_PCCFG(Controller).CanBusOffProcessing)
    {
        canRegs->Nipr |= (uint32)((CAN_BUSOFF_INT_LINE(realController) << 4) | CAN_BUSOFF_INT_LINE(realController));
    }

    /* Reset port control register */
    canRegs->Npcr = CAN_CNTRL_PCCFG(Controller).CanNpcr;

    /* Rest error control register */
    canRegs->Necnt = CAN_NECNT_EWRNLVL;

    /* Set bit timimg register */
    canRegs->Nbtr = Config->CanNbtr;

    /* Rest CAN frame counter register */
    canRegs->Nfcr = CAN_NFCR_FRAME_CFC;

    /* init all mailboxs */
    Can_InitMB(Controller);

    return;

}

/******************************************************************************/
/*
 * Brief               <This function performs controller init message buffer  process>
 * Param-Name[in]      <Controller- CAN controller to be Mode process>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
STATIC FUNC(void, CAN_CODE) Can_InitMB(uint8 Controller)
{
    Can_NodeRegPtrType canRegs = CAN_CNTRL_REG(Controller);
    Can_MbRegPtrType mbRegs; 
    uint8  hwObjId   = 0U;
    uint8  endHwObj  = 0U;
    uint32 timeOut   = 0U;
    uint8  realController = 0U;
    uint32 idType    = 0U;

    realController = CAN_CNTRL_PCCFG(Controller).CanControllerRelId;

    /* 
     * Init Receive Hardware Object 
     */
    endHwObj = (uint8)(CAN_CNTRL_CFG(Controller).CanRxHwObjFirst 
                        + CAN_CNTRL_CFG(Controller).CanRxHwObjCount);
    for (hwObjId = CAN_CNTRL_CFG(Controller).CanRxHwObjFirst; hwObjId < endHwObj; hwObjId++)
    {
        /* Allocate MOs for list */
        CAN_LIST_STATIC_ALLOC(realController+1U, hwObjId);

        timeOut = CAN_TIMEOUT_DURATION;
        while((timeOut > 0U) && (CAN_PNCTR_BUSY == (CAN_PNCTR_REG & CAN_PNCTR_BUSY)))
        {
            timeOut--;
        }

        if(0U == timeOut)
        {
            Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED);
            break;
        }

        /* Mb address */
        mbRegs = CAN_MB_REG(hwObjId);

        /* Set rx mb register */
        mbRegs->Mctstr = CAN_RX_MB_SET;

        mbRegs->Moipr = CAN_RX_INT_LINE(realController) | ((uint32)hwObjId << 8U);

        idType = 0x00000001U & (~(CAN_HWOBJ_CFG(hwObjId).CanIdValue & 0x80000000U) >> 31U);

        mbRegs->Moar = (CAN_HWOBJ_CFG(hwObjId).CanIdValue << (18U * idType)) \
                       | (CAN_MBID_ID_EXTENDED & (~(idType << 29U))) | CAN_PRI_CLASS_ID;

        mbRegs->Moamr = (CAN_HWOBJ_CFG(hwObjId).CanFilterMask << (18U*idType)) 
            | (CAN_ENABLE_MIDE & (~((uint32)CAN_HWOBJ_CFG(hwObjId).CanIdType << 28U)));

        /* Set Message Valid */
        mbRegs->Mctstr = CAN_MSG_VALID;
    }

    /* 
     * Init Transmit Hardware Object
     */
    endHwObj = (uint8)(CAN_CNTRL_CFG(Controller).CanTxHwObjFirst
                      + CAN_CNTRL_CFG(Controller).CanTxHwObjCount);
    for (hwObjId = CAN_CNTRL_CFG(Controller).CanTxHwObjFirst; hwObjId < endHwObj; hwObjId++)
    {
        /* Allocate MOs for list */
        CAN_LIST_STATIC_ALLOC(realController+1U, hwObjId);

        timeOut = CAN_TIMEOUT_DURATION;
        while((timeOut > 0U) && (CAN_PNCTR_BUSY == (CAN_PNCTR_REG & CAN_PNCTR_BUSY)))
        {
            timeOut--;
        }

        if(0U == timeOut)
        {
            Dem_ReportErrorStatus(CAN_E_TIMEOUT, DEM_EVENT_STATUS_FAILED);
            break;
        }

        /* Mb address */
        mbRegs = CAN_MB_REG(hwObjId);

        /* Set tx mb register */
        mbRegs->Mctstr = CAN_TX_MB_SET;

        mbRegs->Moipr = (CAN_TX_INT_LINE(realController) << 4U) | ((uint32)hwObjId << 8U);
    }

    return;
}

#if(STD_ON == CAN_MULTIPLEXED_TRANSMISSION)
/******************************************************************************/
/*
 * Brief               <find lowest priority mailbox for same hth>
 * Param-Name[in]      <Hth - HW-transmit handle>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
STATIC FUNC(uint8, CAN_CODE) Can_FindLowPriorityMb(uint8 Hth)
{
    uint8  hwObjId  = 0U;
    uint8  retHwObj = CAN_HWOBJ_ID(Hth);
    uint32 CanId    = 0U; 

    if (FALSE == Can_IsTxMbFree(retHwObj))
    {
        CanId = Can_GetMBCanId(retHwObj);
        hwObjId = (uint8)(retHwObj+1U);
        while ((hwObjId < CAN_HWOBJ_NUM) && (Hth == CAN_HWOBJ_CFG(hwObjId).CanObjectId))
        {
            if (TRUE == Can_IsTxMbFree(hwObjId))
            {
                retHwObj = hwObjId;
                break;
            }
            else if (TRUE == Can_PriorityHigher(CanId, Can_GetMBCanId(hwObjId)))
            {
                retHwObj = hwObjId;
                CanId = Can_GetMBCanId(hwObjId);
            }
            else
            {
                /* do nothing */
            }

            hwObjId++;
        }
    }

    return retHwObj;
}
#endif /* STD_ON == CAN_MULTIPLEXED_TRANSMISSION */

/******************************************************************************/
/*
 * Brief               <check a mailbox if free, can transmit pdu>
 * Param-Name[in]      <HwObjId - hardware object index>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
STATIC FUNC(boolean, CAN_CODE) Can_IsTxMbFree(uint8 HwObjId)
{
    Can_MbRegPtrType mbRegs;
    boolean retVal = FALSE;

    /* Mb address */
    mbRegs = CAN_MB_REG(HwObjId);

    /* Mb is free */
    if (0U == (mbRegs->Mctstr & CAN_RES_MSGVAL))
    {
        retVal = TRUE;
    }
    return retVal;
}

/******************************************************************************/
/*
 * Brief               <Write PDU into mailbox to Transmit request>
 * Param-Name[in]      <HwObjId - hardware object id>
 * Param-Name[in]      <PduInfo - pdu information>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
STATIC FUNC(void, CAN_CODE) Can_WriteMb(uint8 HwObjId, 
        P2CONST(Can_PduType, AUTOMATIC, CAN_APPL_DATA) PduInfo)
{
    Can_MbRegPtrType mbRegs;
    uint8  controller = 0U;
    uint8  i = 0U;
    uint32 idType = 0U;

    controller = CAN_HWOBJ_CFG(HwObjId).CanControllerRef;

    /* Mb address */
    mbRegs = CAN_MB_REG(HwObjId);

    /* 
     * Set NEWDAT bit to prevent the automatic reset 
     * of TXRQ at the end of an ongoing transmision 
     */
    mbRegs->Mctstr = CAN_RES_NEWDAT_MASK;

    /* Id */
    idType = 0x00000001U & (~(PduInfo->id & 0x80000000U) >> 31U);
    mbRegs->Moar = (PduInfo->id << (18U * idType)) \
                   | (CAN_MBID_ID_EXTENDED & (~(idType << 29U))) | CAN_PRI_CLASS_ID;

    /* DLC */
    /* Clear DLC */
    mbRegs->Mofcr &= 0xF0FFFFFFU;
    mbRegs->Mofcr |= (uint32)PduInfo->length << 24U;

    /* SDU */
    for (i = 0U; i < PduInfo->length; i++)
    {
        mbRegs->Modata[i] = PduInfo->sdu[i];
    }

    /* save pdu handle */
    Can_TxPduHandles[HwObjId] = PduInfo->swPduHandle;

    /* Set Message Valid */
    mbRegs->Mctstr = CAN_MSG_VALID;

    /* send request */
    mbRegs->Mctstr = CAN_SET_TXRQ;

    return;
}

#if ((STD_ON==CAN_HW_TRANSMIT_CANCELLATION)||(STD_ON==CAN_MULTIPLEXED_TRANSMISSION))
/******************************************************************************/
/*
 * Brief               <get can id from specific mailbox hardware>
 * Param-Name[in]      <HwObjId- hardware object id>
 * Param-Name[in/out]  <None>
 * Return              <Can ID>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
STATIC FUNC(uint32, CAN_CODE) Can_GetMBCanId(uint8 HwObjId)
{
    Can_MbRegPtrType mbRegs;
    uint32 canId = 0U;

    /* Mb address */
    mbRegs = CAN_MB_REG(HwObjId);

    /* extended frame */
    if (CAN_MBID_ID_EXTENDED == (mbRegs->Moar & CAN_MBID_ID_EXTENDED))
    {
        canId = mbRegs->Moar & (~CAN_MBID_ID_EXTENDED) & (~CAN_PRI_CLASS_ID);
        canId |= 0x80000000U;  /* CanIf need extended Canid set 31 bit */
    } 
    /* standard frame */
    else
    {
        canId = (mbRegs->Moar & CAN_MBID_ID_STANDARD) >> 18U;
    }

    return canId;
}
#endif /* (STD_ON==CAN_HW_TRANSMIT_CANCELLATION)||(STD_ON==CAN_MULTIPLEXED_TRANSMISSION) */

/******************************************************************************/
/*
 * Brief               <get PDU from specific mailbox hardware>
 * Param-Name[in]      <mbId    - mailbox index>
 * Param-Name[in/out]  <pdu     - pdu>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
STATIC FUNC(void, CAN_CODE) Can_GetMBInfo(uint8 HwObjId, 
                                P2VAR(Can_PduType, AUTOMATIC, AUTOMATIC) pdu)
{
    Can_MbRegPtrType mbRegs;
    uint8 i = 0U;

    /* Mb address */
    mbRegs = CAN_MB_REG(HwObjId);

    /* ID */
    if(0U != (mbRegs->Moar & CAN_IDE))  /* extended frame */
    {
        pdu->id = mbRegs->Moar & (~CAN_MBID_ID_EXTENDED) & (~CAN_PRI_CLASS_ID);
        pdu->id |= 0x80000000U;   /* CanIf need extended Canid set 31 bit */
    }
    else /* standard frame */
    {
        pdu->id = (mbRegs->Moar & CAN_MBID_ID_STANDARD) >> 18U;
    }

    /* DLC */
    pdu->length = (uint8)((mbRegs->Mofcr & CAN_MBCS_LENGTH) >> 24U);

    /* SDU */
    for (i = 0U; i < pdu->length; i++) /* @req <CAN299> */
    {
        pdu->sdu[i] = mbRegs->Modata[i];
    }

    return;
}

#if ((STD_ON==CAN_HW_TRANSMIT_CANCELLATION)||(STD_ON==CAN_MULTIPLEXED_TRANSMISSION))
/******************************************************************************/
/*
 * Brief               <compare two canid priority>
 * Param-Name[in]      <destId - destination Can ID>
 * Param-Name[in]      <srcId  - source Can ID>
 * Return              <TRUE: destId higher than srcId, 
 *                      FALSE: destId not higher than srcId>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
STATIC FUNC(boolean, CAN_CODE) Can_PriorityHigher(Can_IdType destId, Can_IdType srcId)
{
    boolean ret = FALSE;

    /* clear bit 29, 30 */
    destId &= 0x9FFFFFFFU;
    srcId  &= 0x9FFFFFFFU;

    /* low 11 bit same, then compare high 21 bit */
    if ((destId & 0x7FFU) == (srcId & 0x7FFU)) 
    {
        /* compare high 21 bit */
        if ((destId & 0xFFFFF800U) < (srcId & 0xFFFFF800U))
        {
            ret = TRUE;    
        }
        else
        {
            ret = FALSE;
        }
    }
    else if ((destId & 0x7FFU) < (srcId & 0x7FFU))
    {
        ret = TRUE;
    }
    else
    {
        ret = FALSE;
    }

    return ret;
}
#endif /* (STD_ON==CAN_HW_TRANSMIT_CANCELLATION)||(STD_ON==CAN_MULTIPLEXED_TRANSMISSION) */

/******************************************************************************/
/*
 * Brief               <Enable interrupt when state is started>
 * Param-Name[in]      <Controller>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
STATIC FUNC(void, CAN_CODE) Can_StartStateEnableInt(uint8 Controller)
{
    Can_NodeRegPtrType canRegs;
    Can_MbRegPtrType mbRegs;
    uint8  hwObjId   = 0U;
    uint8  endHwObj  = 0U;
    uint8  realController = 0U;

    realController = CAN_CNTRL_PCCFG(Controller).CanControllerRelId;
    canRegs = CAN_CNTRL_REG(Controller);

    /* 
     * Enabel Rx/Tx/Busoff interrupt, set interrupt pointer  
     */
    if (CAN_PROCESS_TYPE_INTERRUPT == CAN_CNTRL_PCCFG(Controller).CanRxProcessing) 
    {
        /* Enable mb interrupt */
        endHwObj = (uint8)(CAN_CNTRL_CFG(Controller).CanRxHwObjFirst 
                            + CAN_CNTRL_CFG(Controller).CanRxHwObjCount);
        for (hwObjId = CAN_CNTRL_CFG(Controller).CanRxHwObjFirst; hwObjId < endHwObj; hwObjId++)
        {
            /* Mb address */
            mbRegs = CAN_MB_REG(hwObjId);

            /* Enable mb rx interrupt */
            mbRegs->Mofcr |= CAN_MB_RX_INT_ENABLE;
        }
    }
    if (CAN_PROCESS_TYPE_INTERRUPT == CAN_CNTRL_PCCFG(Controller).CanTxProcessing)
    {
        endHwObj = (uint8)(CAN_CNTRL_CFG(Controller).CanTxHwObjFirst
                          + CAN_CNTRL_CFG(Controller).CanTxHwObjCount);
        for (hwObjId = CAN_CNTRL_CFG(Controller).CanTxHwObjFirst; hwObjId < endHwObj; hwObjId++)
        {
            /* Mb address */
            mbRegs = CAN_MB_REG(hwObjId);

            /* Enabel mb tx interrupt */
            mbRegs->Mofcr |= CAN_MB_TX_INT_ENABLE;
        }
    }
    if (CAN_PROCESS_TYPE_INTERRUPT == CAN_CNTRL_PCCFG(Controller).CanBusOffProcessing)
    {
        /* Enabel busoff/LEC interrupt */
        canRegs->Ncr |= CAN_ENABLE_BUSOFF_INT;
    }

    return; 
}

/******************************************************************************/
/*
 * Brief               <Disable interrupt >
 * Param-Name[in]      <Controller>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
STATIC FUNC(void, CAN_CODE) Can_DisableInt(uint8 Controller)
{
    Can_NodeRegPtrType canRegs;
    Can_MbRegPtrType mbRegs;
    uint8 hwObjId   = 0U;
    uint8 endHwObj  = 0U;

    canRegs = CAN_CNTRL_REG(Controller);
    if (CAN_PROCESS_TYPE_INTERRUPT == CAN_CNTRL_PCCFG(Controller).CanRxProcessing) 
    {
        /* Enable mb interrupt */
        endHwObj = (uint8)(CAN_CNTRL_CFG(Controller).CanRxHwObjFirst 
                            + CAN_CNTRL_CFG(Controller).CanRxHwObjCount);
        for (hwObjId = CAN_CNTRL_CFG(Controller).CanRxHwObjFirst; hwObjId < endHwObj; hwObjId++)
        {
            /* Mb address */
            mbRegs = CAN_MB_REG(hwObjId);

            /* Didable mb rx interrupt */
            mbRegs->Mofcr &= ~CAN_MB_RX_INT_ENABLE;
        }
    }
    if (CAN_PROCESS_TYPE_INTERRUPT == CAN_CNTRL_PCCFG(Controller).CanTxProcessing)
    {
        endHwObj = (uint8)(CAN_CNTRL_CFG(Controller).CanTxHwObjFirst
                          + CAN_CNTRL_CFG(Controller).CanTxHwObjCount);
        for (hwObjId = CAN_CNTRL_CFG(Controller).CanTxHwObjFirst; hwObjId < endHwObj; hwObjId++)
        {
            /* Mb address */
            mbRegs = CAN_MB_REG(hwObjId);

            /* Set mb tx interrupt */
            mbRegs->Mofcr &= ~CAN_MB_TX_INT_ENABLE;
        }
    }
    if (CAN_PROCESS_TYPE_INTERRUPT == CAN_CNTRL_PCCFG(Controller).CanBusOffProcessing)
    {
        /* Disabel busoff interrupt */
        canRegs->Ncr &= ~CAN_ENABLE_BUSOFF_INT;
    }
    return;
}

/******************************************************************************/
/*
 * Brief               <This function performs write CAN_WDT_CON0 value>
 * Param-Name[in]      <wdtCon0 - the value of CAN_WDT_CON0>
 * Param-Name[out]     <None>
 * Param-Name[in/out]  <None>
 * Return              <None>
 * PreCondition        <None>
 * CallByAPI           <None>
 */
/******************************************************************************/
STATIC FUNC(void, CAN_CODE) Can_WriteWDTCON0(uint32 wdtCon0)
{
    uint32 Dummy;

    Dummy = CAN_WDT_CON0;  
    Dummy |=  0x000000F0U;         /* set HWPW1 = 1111b */

    if(0 != (CAN_WDT_CON1 & CAN_WDT_CON1_DR))
    {
        Dummy |=  0x00000008U;     /* set HWPW0 = WDTDR */
    }
    else
    {
        Dummy &= ~0x00000008U;     /* set HWPW0 = WDTDR */
    }
    if(0 != (CAN_WDT_CON1 & CAN_WDT_CON1_IR))
    {
        Dummy |=  0x00000004U;     /* set HWPW0 = WDTIR */
    }
    else
    {
        Dummy &= ~0x00000004U;     /* set HWPW0 = WDTIR */
    }

    Dummy &= ~0x00000002U;        /* set WDTLCK = 0 */
    CAN_WDT_CON0 = Dummy;             /* unlock access */

    wdtCon0 |=  0x000000F2U;      /* set HWPW1 = 1111b and WDTLCK = 1 */
    wdtCon0 &= ~0x0000000CU;      /* set HWPW0 = 00b */
    CAN_WDT_CON0 =  wdtCon0;          /* write access and lock */
}

#define CAN_STOP_SEC_CODE
#include "Can_MemMap.h"
/*=======[E N D   O F   F I L E]==============================================*/

